//简单函数，如fn foo(p1: i32, p2: i32) -> i32 {}
use syn::{ItemFn};

use crate::{rules::r_fn_block, tree::t_fn::{self, BlockType}};
pub fn visit(fn_item:ItemFn) ->t_fn::TFn{
    let fn_name = fn_item.sig.ident.to_string();
    let params = extract_params(&fn_item);
    let return_type = extract_ret_ty(&fn_item);
    let mut block_type = BlockType::Fn;
    if return_type!="()"{
        block_type = BlockType::FnRet;
    }
    let t_fn = t_fn::TFn{
        name: fn_name,
        params,
        bbns: r_fn_block::visit(*fn_item.block, block_type),
        return_type,
    };

    t_fn
}

fn extract_ret_ty(fn_item: &ItemFn) -> String {
    let ret_ty = match &fn_item.sig.output {
        syn::ReturnType::Type(_, ty) => {
            match **ty {
                syn::Type::Path(ref type_path) => {
                    type_path.path.segments.last().unwrap().ident.to_string()
                },
                _ => "()".to_string(),
            }
        },
        syn::ReturnType::Default => "()".to_string(),
    };
    ret_ty
}

fn extract_params(fn_item: &ItemFn) -> Vec<(String, String)> {
    let params = fn_item.sig.inputs.iter().filter_map(|arg| {
        if let syn::FnArg::Typed(pat_type) = arg {
            if let syn::Pat::Ident(pat_ident) = *pat_type.pat.clone() {
                let param_name = pat_ident.ident.to_string();
                let param_type = match *pat_type.ty.clone() {
                    syn::Type::Path(type_path) => {
                        type_path.path.segments.last().unwrap().ident.to_string()
                    },
                    _ => "unknown".to_string(),
                };
                return Some((param_name, param_type));
            }
        }
        None
    }).collect::<Vec<(String, String)>>();
    params
}
